function isPlainObject(obj) {
	var key;
	if (!obj || typeof obj !== "object" || obj.nodeType) {
		return false;
	}
	try {
		if (obj.constructor &&
			!hasOwn.call(obj, "constructor") &&
			!hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
			return false;
		}
	} catch (e) {
		return false;
	}
	for (key in obj) {}
	return key === undefined || hasOwn.call(obj, key);
}

function getTime(d, pattern) {
	d = d ? new Date(d) : new Date();
	pattern = pattern || 'yyyy-MM-dd';
	var y = d.getFullYear().toString(),
		o = {
			M: d.getMonth() + 1,
			d: d.getDate(),
			h: d.getHours(),
			m: d.getMinutes(),
			s: d.getSeconds()
		};
	pattern = pattern.replace(/(y+)/ig, function(a, b) {
		return y.substr(4 - Math.min(4, b.length));
	});
	for (var i in o) {
		pattern = pattern.replace(new RegExp('(' + i + '+)', 'g'), function(a, b) {
			return (o[i] < 10 && b.length > 1) ? '0' + o[i] : o[i];
		});
	}
	return pattern;
}

function stringify(obj) {
	//console.log(obj)
	if (null === obj)
		return "null";
	if ("string" !== typeof obj && "undefined" !== typeof obj && obj.toJSON)
		return obj.toJSON();
	var type = (Array.isArray || _instanceOf(Array))(obj) && "array" || typeof obj;
	//console.log(type)
	switch (type) {
		case "string":
			return '"' + obj.replace(/\"/gim, "\'").replace(/\s+/gim, " ").replace(/[\r\n\t\\]+/gim, function(a) {
				return "\\" + a;
			}) + '"';
		case "number":
			var ret = obj.toString();
			return /N/.test(ret) ? "null" : ret;
		case "boolean":
			return obj.toString();
		case "date":
			return "new Date(" + obj.getTime() + ")";
		case "array":
			for (var ar = [], i = 0; i < obj.length; i++)
				ar[i] = stringify(obj[i]);
			return "[" + ar.join(",") + "]";
		case "object":
			//console.log(isPlainObject(obj), obj)
			if (isPlainObject(obj)) {
				ar = [];
				for (var i in obj)
					ar.push('"' + i.replace(/[\"\r\n\t\\]+/gim, function(a) {
						return "\\" + a
					}) + '":' + stringify(obj[i]));
				return "{" + ar.join(",") + "}"
			}
	}
	return "null"
}

function extend(a, b) {
	for (var i in b) a[i] = b[i];
	return a;
}

function tmpl(b, a) {
	for (var n in a) b = b.replace(new RegExp("{{\\s*" + n + "\\s*}}", "gim"), a[n]);
	return b;
};

class Cache {
	constructor() {
		this.data = {};
		return this;
	}
	commit(data) {
		extend(this.data, data);
		return this;
	}
	get(name) {
		return this.data[name];
	}
	remove(name) {
		if (this.data[name])
			delete this.data[name];
		return this;
	}
	has(name) {
		return (name in this.data);
	}
}

exports.cache = function(){
	return new Cache();
}

var redis = require("redis"),
	s_config = require("./user/server-config.js").config
exports.radisClient = function(callback){
	var client = redis.createClient({port: 6379, host: s_config.ip, no_ready_check: true});
	client.on('error',function(error){
	    console.log(error);
	});
	client.on('connect', function(error){
		console.log('success '+error);
		callback && callback(client);
	});
	return client;
};

exports.isPlainObject = isPlainObject;
exports.getTime = getTime;
exports.stringify = stringify;
exports.extend = extend;
exports.tmpl = tmpl;
exports.md5 = function(data) {
	var Buffer = require("buffer").Buffer;
	var buf = new Buffer(data);
	var str = buf.toString("binary");
	var crypto = require("crypto");
	return crypto.createHash("md5WithRSAEncryption").update(str).digest("hex");
};